#include "Testcase.h"
#include <stdio.h>

int i, temp, j;
int PnodeId1, PnodeId2, PnodeId3, PnodeId0, PnodeId4, n;
int A = 1, B = 101;
int PnodeIdArr[200];
int UserNumOnNode[10];

void testcase1(void) {
    //  Test 1: simple test
	ConnectReq (A); // User A connect to Server, Server control 3 nodes 

	PnodeId1 = GetPnodeByUser(A); // Get node number assigned to user A 
	assert(PnodeId1 != -1);

	PnodeId2 = GetPnodeByUser(A+1);
	assert(PnodeId2 == -1);

	n = GetUserNumByPnode (PnodeId1); // Get user number on node PnodeId
	assert(n == 1);

	ReleaseReq(A); // User A left

	n = GetUserNumByPnode (PnodeId1);
	assert(n == 0);
}

void testcase2(void) {
    // Test 2: duplicate release
	ConnectReq (A);
	PnodeId1 = GetPnodeByUser(A); 
	assert(PnodeId1 != -1);
    ReleaseReq(B);
    ReleaseReq(B);
    ReleaseReq(B);
	PnodeId2 = GetPnodeByUser(A); 
	assert(PnodeId2 == PnodeId1);
    n = GetUserNumByPnode (PnodeId1);
	assert(n == 1);
	ReleaseReq(A);
	ReleaseReq(A);
	ReleaseReq(A);
	PnodeId2 = GetPnodeByUser(A); 
	assert(PnodeId2 == -1);
	PnodeId2 = GetPnodeByUser(B); 
	assert(PnodeId2 == -1);
	n = GetUserNumByPnode (PnodeId1);
	assert(n == 0);
}

void testcase3(void) {
    //  Test 3: many add then delete all
    
    for (i=0;i<100; i++){
        ConnectReq(A+i);
        PnodeId1 = GetPnodeByUser(A+i);
        assert(PnodeId1 != -1);
        n = GetUserNumByPnode(PnodeId1);
        assert(n>=(i+1)/3 && n<=(i+1)/3+1);
    }
    for (i=0;i<100; i++){
         ReleaseReq(A+i);
         PnodeId1 = GetPnodeByUser(A+i);
         assert(PnodeId1 == -1);
    }
    
}

void testcase4(void) {
    // Test 4: release all user on a fixed node then add new users on it
	
    
    for (i=0;i<100; i++){
        ConnectReq(A+i);
        PnodeId1 = GetPnodeByUser(A+i);
        assert(PnodeId1 != -1);
    }   
    for (i=0;i<100; i++){  
        PnodeId2 = GetPnodeByUser(A+i);
        if (PnodeId2 == PnodeId1){     // release used on PnodeId1
            ReleaseReq(A+i);         
        }
    }    
    n = GetUserNumByPnode(PnodeId1);
    assert(n == 0);
    for (i=0 ; i<33; i++){
        ConnectReq(B+i);
        PnodeId2 = GetPnodeByUser(B+i);
        assert(PnodeId2 == PnodeId1);
        n = GetUserNumByPnode(PnodeId1);
        assert(n == i+1);
    }
    for (i=0; i<200; i++){
        ReleaseReq(A+i);
    }

}

void testcase5(void) {
    // Test 5: many query                   
    
    for (i=0;i<10;i++){
        ConnectReq(A+i);
        PnodeIdArr[A+i] = GetPnodeByUser(A+i);
        assert(PnodeIdArr[A+i] != -1);    
        n = GetUserNumByPnode(PnodeIdArr[A+i]);
        assert(n>0);
        UserNumOnNode[PnodeIdArr[A+i]] = n;
    }            
	for (i=0;i<255;i++){
        PnodeId1 = GetPnodeByUser(A+i%10);
        assert(PnodeId1 == PnodeIdArr[A+i%10]);
        n = GetUserNumByPnode(PnodeId1);    
        assert(n == UserNumOnNode[PnodeId1]);
    }
    for (i=0; i<10; i++){
        ReleaseReq(A+i);
    }
    
}

void testcase6(void) {
    // Test 6: simple complex test
    ConnectReq(A);
    PnodeId1 = GetPnodeByUser(A);
    ConnectReq(A+1);
    PnodeId2 = GetPnodeByUser(A+1);
    ConnectReq(A+2);
    PnodeId3 = GetPnodeByUser(A+2);
    assert(PnodeId1 != PnodeId2);
    assert(PnodeId2 != PnodeId3);
    assert(PnodeId3 != PnodeId1);
    ReleaseReq(A+1);
    ConnectReq(A+3);
    PnodeId0 = GetPnodeByUser(A+3);
	assert(PnodeId0 == PnodeId2);
    ConnectReq(A+4);
    ConnectReq(A+5);
    ConnectReq(A+6);
    PnodeId0 = GetPnodeByUser(A+5);
	ReleaseReq(A+5);
    if (PnodeId0 == PnodeId1) ReleaseReq(A);
    if (PnodeId0 == PnodeId2) ReleaseReq(A+3);
    if (PnodeId0 == PnodeId3) ReleaseReq(A+2);
    ReleaseReq(A+6);
    ConnectReq(A+7);
    PnodeId4 = GetPnodeByUser(A+7);
    assert(PnodeId4 == PnodeId0);    
    n = GetUserNumByPnode(PnodeId0);
	assert(n == 1);
    
    for (i=0; i<8; i++){
        ReleaseReq(A+i);
    }
}

void testcase7(void) {
    // Test 7: duplicate add and delete
    for (j=0;j<10;j++) PnodeIdArr[j] = -1;
    for (i=1;i<100;i++){
        for (j=0;j<10;j++){
            if ((i%(A+j))!=0){
               temp = PnodeIdArr[j];
               ConnectReq(A+j);
               PnodeId1 = GetPnodeByUser(A+j);
               if (temp!=-1) assert(PnodeId1 == temp);
            }else{
               ReleaseReq(A+j);   
               PnodeId1 = GetPnodeByUser(A+j);
               assert(PnodeId1 == -1);
            }
            PnodeIdArr[j] = PnodeId1;
        }
    }
    for (i=0; i<10; i++){
        ReleaseReq(A+i);
    }
}
